A message is an atomic piece of data stored in a queue. Each message
in Windows Azure queues can be up to 8 KB in size. There is no limit on
the number of messages in a queue, or the combined size of the messages
you can put in the store. Messages can be in any format.However, there is one “gotcha” here that you should be aware of.
Though you typically insert messages in binary format, when you read them
back out from the queue you’ll get them in base64 encoding. If you’re
writing your own client, remember to decode them back to their binary
representation.
1. Enqueuing a Message
Enqueuing a message adds a message to the back of the queue. To
enqueue a message to a queue, send an authentic and properly formatted
HTTP POST to
http://<account>.queue.core.windows.net/<queuename>/messages.
The request body must be in the following form:
<QueueMessage>
<MessageText>message-content</MessageText>
</QueueMessage>
Most storage client libraries base64-encode the message and decode
the message when reading it. The queue service itself expects the
message contents to be UTF8-compatible.
Example 1 shows how to use the official
storage client library to post a new message to the queue testq1.
Example 1. Adding a message
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(ConfigurationSettings.AppSettings ["DataConnectionString"]); CloudQueueClient cloudQueueClient = cloudStorageAccount.CreateCloudQueueClient();
CloudQueue cloudQueue = cloudQueueClient.GetQueueReference("testq1"); CloudQueueMessage msg = new CloudQueueMessage("Sample Message"); cloudQueue.AddMessage(msg);
|
This code gets a handle to the queue testq1 (it assumes the queue has already been
created) and then inserts a small message with the contents "Sample message". Following is the HTTP
traffic for creating the message. Note how the message is base64-encoded
in the request body.
POST /testq1/messages?timeout=30 HTTP/1.1
x-ms-date: Sat, 04 Jul 2009 00:53:26 GMT
Authorization: SharedKey sriramk:26L5qqQaIX7/6ijXxvbt3x1AQW2/Zrpxku9WScYxD4U=
Host: sriramk.queue.core.windows.net
Content-Length: 76
Expect: 100-continue
<QueueMessage>
<MessageText>U2FtcGxlIG1lc3NhZ2U=</MessageText>
</QueueMessage>
If the message was successfully created (which it was in this
case), the server sends down an HTTP 201
Created message as an acknowledgment:HTTP/1.1 201 Created
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: adaa5b64-c737-4a36-be98-dc8b712a264e
Date: Sat, 04 Jul 2009 00:51:23 GMT
Content-Length: 0
Enqueuing a message adds it at the end of the queue. However, that
doesn’t necessarily mean you’ll get the message in order, after all the
messages you have inserted. Remember that one of the flipsides of using
a large, distributed queue service is that the order in which the
messages are delivered is almost never guaranteed.
2. Understanding Message TTL
Every message has a TTL that is set, by default, to seven days.
This is the amount of time after which the message is automatically
deleted. You can specify the TTL for the message by adding the parameter
messagettl=ttl-in-seconds
to the URI. The storage client library also has an equivalent method
overload to set the TTL for the message you’re inserting.
3. Peeking at a Message
You already saw how retrieving a message alters the visibility
of the message. Peeking at a message is a quick way to view the messages
at the front of the queue without having to change their visibility. It
lets you see what kind of messages you’re going to get before you have
to deal with them.
To peek at messages in a queue, send an HTTP GET to
http://<account>.core.windows.net/<queue>/messages?peekonly=true.
You can control how many messages you want to peek at by setting the
numofmessages parameter in the
URI.
If the request is correct, the server sends down an XML response
of the following form:
<QueueMessagesList>
<QueueMessage>
<MessageId>string-message-id</MessageId>
<InsertionTime>insertion-time</InsertionTime>
<ExpirationTime>expiration-time</ExpirationTime>
<MessageText>message-body</MessageText>
</QueueMessage>
</QueueMessagesList>
Note:
There is no guarantee that the server will actually retrieve the
number of messages you asked for.
The following code shows how to use the storage client library to
peek at a message:
CloudStorageAccount cloudStorageAccount =
CloudStorageAccount.Parse(ConfigurationSettings.AppSettings
["DataConnectionString"]);
CloudQueueClient cloudQueueClient =
cloudStorageAccount.CreateCloudQueueClient();
CloudQueue cloudQueue = cloudQueueClient.GetQueueReference("testq1");
CloudQueueMessage msg = cloudQueue.PeekMessage();
Console.WriteLine(msg.AsString);
This conjures up a handle to the queue, and then tries to peek at
one message of the queue. Once it gets the message, it tries to write
the message’s contents to the console. Following is the HTTP capture of
this operation that shows that one message is in the queue with the
contents "Sample Message", which gets
base64-encoded:GET /testq1/messages?numofmessages=1&peekonly=True&timeout=30 HTTP/1.1
x-ms-date: Sat, 04 Jul 2009 11:17:11 GMT
Authorization: SharedKey sriramk:JVCMBcl0QQKSsOMBeZxia49MxWJ7OSASSSuVtEyEddc=
Host: sriramk.queue.core.windows.net
Connection: Keep-Alive
The server sends down an XML-formatted list containing the actual
message contents, as well as MessageIds, and insertion and expiration
times:HTTP/1.1 200 OK
Content-Type: application/xml
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: c43f366d-88c0-4000-9c60-ba8844106fb2
Date: Sat, 04 Jul 2009 11:15:51 GMT
Content-Length: 337
<?xml version="1.0" encoding="utf-8"?>
<QueueMessagesList>
<QueueMessage>
<MessageId>bc5349e6-2a1c-4b39-a149-
2ef3ab60e28a</MessageId>
<InsertionTime>Sat, 04 Jul 2009 00:54:47 GMT</InsertionTime>
<ExpirationTime>Sat, 11 Jul 2009 00:46:52 GMT</ExpirationTime>
<MessageText>U2FtcGxlIG1lc3NhZ2U=</MessageText>
</QueueMessage>
</QueueMessagesList>
4. Getting Messages
Now it’s time to examine one of the most critical operations:
getting messages. You can get messages from a specific queue by sending
an authorized HTTP GET to
http://<account>.core.windows.net/<queue>/messages.
There are two parameters you can modify here:
The first, numofmessages,
specifies the number of messages you want the queue service to
return. By default, you get one message back.
Note:
There is no guarantee that the queue service will actually
return the number of messages you want, even if they exist in the
queue at that time.
The second, visibilitytimeout, specifies the
visibility timeout of the messages you’re retrieving. In short, when you get messages
off a queue, the queue service automatically makes them invisible to
give you time to process them. If you don’t delete the message
before the timeout expires (typically because you experienced an
error), the queue service makes the message visible again so that
some other queue receiver can get a chance to process the
message.
The following code shows how to use the Microsoft storage client
library to get a message off the queue. In this case, you use the
default visibility timeout of two hours:
CloudStorageAccount cloudStorageAccount =
CloudStorageAccount.Parse(ConfigurationSettings.AppSettings
["DataConnectionString"]);
CloudQueueClient cloudQueueClient =
cloudStorageAccount.CreateCloudQueueClient();
CloudQueue cloudQueue = cloudQueueClient.GetQueueReference("testq1");
CloudQueueMessage msg = cloudQueue.GetMessage();
//Do something useful with the message
cloudQueue.DeleteMessage(msg);
Following is the HTTP request for the same operation. Note that
the numofmessages parameter is
optional—if it is not specified, you’ll get one message back:GET /testq1/messages?numofmessages=1&timeout=30 HTTP/1.1
x-ms-date: Sat, 04 Jul 2009 00:56:52 GMT
Authorization: SharedKey sriramk:u0Js1nLfeDl3a8N79TAZWvrDpK9a/AgwpwcoIS7T/BU=
Host: sriramk.queue.core.windows.net
Following is the HTTP response for this request. The server sends
down an XML response containing the message contents, along with a few
interesting properties:HTTP/1.1 200 OK
Content-Type: application/xml
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 0677a63d-fa82-476d-83e5-f206310b43a0
Date: Sat, 04 Jul 2009 00:54:51 GMT
Content-Length: 454
<?xml version="1.0" encoding="utf-8"?>
<QueueMessagesList>
<QueueMessage>
<MessageId>a59c9817-b54b-4b56-9480-1a40977da588</MessageId>
<InsertionTime>Sat, 04 Jul 2009 00:55:22 GMT</InsertionTime>
<ExpirationTime>Sat, 11 Jul 2009 00:51:23 GMT</ExpirationTime>
<PopReceipt>AgAAAAEAAAAAAAAAIPi8G0L8yQE=</PopReceipt>
<TimeNextVisible>Sat, 04 Jul 2009 00:55:22 GMT</TimeNextVisible>
<MessageText>U2FtcGxlIG1lc3NhZ2U=</MessageText>
</QueueMessage>
</QueueMessagesList>
Apart from the usual suspects (such as expiration time, message
ID, and message contents), the XML response contains two additional
properties you haven’t seen before.
One of them is TimeNextVisible,
which is essentially when the visibility timeout expires and the message
will show up on the queue again. The other is a PopReceipt. Just as a message ID uniquely
identifies a message, a PopReceipt
uniquely identifies each time you take a message off the queue.
5. Deleting Messages
After you’ve taken a message from the queue and finished
processing it, you must delete it to stop it from appearing on the queue
automatically again. To do so, send an HTTP
DELETE to
http://<account>.core.windows.net/<queue>/messages/messageid?popreceipt=<popreceipt>.
Note:
You need the PopReceipt
property obtained from receiving a message to delete it. You can’t
delete a message just by knowing its messageid from a peek operation.
The following code shows how to get a message off the queue using
the Microsoft storage client library and deleting it:
CloudStorageAccount cloudStorageAccount =
CloudStorageAccount.Parse(ConfigurationSettings.AppSettings
["DataConnectionString"]);
CloudQueueClient cloudQueueClient =
cloudStorageAccount.CreateCloudQueueClient();
CloudQueue cloudQueue = cloudQueueClient.GetQueueReference("testq1");
CloudQueueMessage msg = cloudQueue.GetMessage();
//Do something useful with the message
cloudQueue.DeleteMessage(msg);
You already saw the HTTP request-response content for getting
messages. Following is the HTTP traffic for deleting a message. This
assumes you already have a message and have a valid PopReceipt:DELETE /testq1/messages/a59c9817-b54b-4b56-9480-1a40977da588?
popreceipt=AgAAAAEAAAAAAAAAIPi8G0L8yQE%3d&timeout=30 HTTP/1.1
x-ms-date: Sat, 04 Jul 2009 12:47:51 GMT
Authorization: SharedKey sriramk:D+xJP6G29d9z1SdQ61sb4UuJgaqiNwePYjB/pzTweS8=
Host: sriramk.queue.core.windows.net
Content-Length: 0
Connection: Keep-Alive
The server sends down an HTTP 204 if the delete was successful, and the
message instantly disappears off the queue.6. Deleting and Using PopReceipts
Why force users to get a message and use the PopReceipt to delete a message instead of the
messageid? Imagine a world where you
deleted a message just by specifying its ID. Now, imagine multiple queue
receivers each taking different processing times. In this scenario, if a
worker takes too long to process the message, the visibility timeout
would kick in, make the message visible again, and hand the message to
another worker. The first worker could then try to delete the message,
even though some other worker has already started to work on the
message.
The PopReceipt mechanism deals
with this scenario. If your PopReceipt’s visibilitytimeout has expired, your delete
operation will fail, thereby ensuring that only the right worker is able
to delete the message off the queue. The key point here is that a
message must be deleted before its visibility timeout expires, and by
the same worker/entity that dequeued that message.